#include "sdlcursesio.h"
#include "symbol.h"
#include "font.h"

SDLCursesIO::SDLCursesIO()
: _xSpace( 0 )
, _ySpace( 0 )
, _font( 0 )
, _screen( 0 )
, _quit( false )
{
}

SDLCursesIO::~SDLCursesIO()
{
}

void SDLCursesIO::InitInternal()
{
    SDL_Init( SDL_INIT_VIDEO );
    SDL_EnableUNICODE( true );
    SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, 60 );

    _xSpace = FONT_WIDTH;
    _ySpace = FONT_HEIGHT;

    _screen = SDL_SetVideoMode( _width * _xSpace, _height * _ySpace, 32, SDL_SWSURFACE );
    if ( !_screen )
        throw std::runtime_error( "Could not initialise SDL video" );

    _font = SDL_CreateRGBSurface( SDL_SWSURFACE, _xSpace * 32, _ySpace * 16, 24, 0, 0, 0, 0 );
    SDL_Rect r;
    r.w = 1;
    r.h = 1;
    for ( uint i = 0; i < _xSpace * 32 * _ySpace * 16; i++ ) {
        if ( FONT[ i ] ) {
            r.x = Sint16( i % ( _xSpace * 32 ) );
            r.y = Sint16( i / ( _xSpace * 32 ) );
            SDL_FillRect( _font, &r, SDL_MapRGB( _font->format, 255, 255, 255 ) );
        }
    }
    SDL_SetColorKey( _font, SDL_SRCCOLORKEY, SDL_MapRGB( _font->format, 255, 255, 255 ) );
}

void SDLCursesIO::DestroyInternal()
{
    SDL_FreeSurface( _font );
    SDL_Quit();
}

void SDLCursesIO::SetTitle( const std::string& title )
{
    SDL_WM_SetCaption( title.c_str(), 0 );
}

void SDLCursesIO::Render( char animation )
{
    SDL_Rect r, t;
    r.x = 0;
    r.y = 0;
    r.w = _screen->w;
    r.h = _screen->h;
    SDL_FillRect( _screen, &r, SDL_MapRGB( _screen->format, 0, 0, 0 ) );

    r.w = t.w = _xSpace;
    r.h = t.h = _ySpace;

    SDL_Surface* s = SDL_CreateRGBSurface( SDL_SWSURFACE, _xSpace, _ySpace, 24, 0, 0, 0, 0 );
    for ( uint x = 0; x < _width; x++ ) {
        for ( uint y = 0; y < _height; y++ ) {

            Sym d;
            Colour bg( 0, 0, 0 );
            for ( int k = LAYERS - 1; k >= 0; k-- ) {
                const SymList& list = ( *_data )[ x ][ y ][ k ];
                const Colour& c = ( *_bg )[ x ][ y ][ k ];
                if ( !list.empty() || c.r != 0 || c.g != 0 || c.b != 0 || k == 0 ) {
                    d = list.empty() ? Sym( 0, Colour( 0, 0, 0 ) ) : list[ animation % list.size() ];
                    bg = c;
                    break;
                }
            }

            r.x = x * _xSpace;
            r.y = y * _ySpace;

            t.x = ( d.first % 32 ) * _xSpace;
            t.y = ( d.first / 32 ) * _ySpace;

            SDL_FillRect( _screen, &r, SDL_MapRGB( _screen->format, bg.r, bg.g, bg.b ) );
            SDL_FillRect( s, 0, SDL_MapRGB( _screen->format, d.second.r, d.second.g, d.second.b ) );
            SDL_BlitSurface( _font, &t, s, 0 );
            SDL_SetColorKey( s, SDL_SRCCOLORKEY, SDL_MapRGB( _screen->format, 0, 0, 0 ) );
            SDL_BlitSurface( s, 0, _screen, &r );
            if ( _coordSet.count( Coord( x, y ) ) > 0 ) {
                SDL_FillRect( s, 0, SDL_MapRGB( _screen->format, 255, 255, 255 ) );
                SDL_SetColorKey( s, 0, 0 );
                SDL_SetAlpha( s, SDL_SRCALPHA, 64 );
                SDL_BlitSurface( s, 0, _screen, &r );
                SDL_SetAlpha( s, 0, 0 );
            }

        }
    }
    SDL_FreeSurface( s );
    SDL_Flip( _screen );
}

uint SDLCursesIO::Input()
{
    SDL_Event e;
    while( true ) {
        SDL_WaitEvent( &e );
        if ( e.type == SDL_KEYDOWN ) {
            if ( e.key.keysym.sym == SDLK_RETURN || e.key.keysym.sym == SDLK_SPACE )
                return INPUT_CONFIRM;
            if ( e.key.keysym.sym == SDLK_ESCAPE )
                return INPUT_CANCEL;
            if ( e.key.keysym.sym == SDLK_UP )
                return INPUT_UPARROW;
            if ( e.key.keysym.sym == SDLK_LEFT )
                return INPUT_LEFTARROW;
            if ( e.key.keysym.sym == SDLK_DOWN )
                return INPUT_DOWNARROW;
            if ( e.key.keysym.sym == SDLK_RIGHT )
                return INPUT_RIGHTARROW;
            if ( e.key.keysym.sym == SDLK_PAGEUP )
                return INPUT_PGUP;
            if ( e.key.keysym.sym == SDLK_PAGEDOWN )
                return INPUT_PGDN;
            if ( e.key.keysym.sym == SDLK_HOME )
                return INPUT_HOME;
            if ( e.key.keysym.sym == SDLK_END )
                return INPUT_END;
            if ( e.key.keysym.sym == SDLK_BACKSPACE )
                return INPUT_BACKSPACE;
            if ( e.key.keysym.unicode < 256 )
                return e.key.keysym.unicode;
        }
        if ( e.type == SDL_QUIT )
            throw QuitException();
    }
    return 0;
}
